﻿@using System.ComponentModel.DataAnnotations
@inject IUserMgmtService userService
@inject IUserStatusService statusService
@inject ILogger<UserDialog> logger

<MudDialog>
    <DialogContent>
        <EditForm autocomplete="off" Model="@model" OnValidSubmit="OnValidSubmit">
            <DataAnnotationsValidator/>
            <MudTextField @bind-Value="@model.Username" For="@(() => model.Username)" Label="User Name" ReadOnly="false" Variant="Variant.Filled" UserAttributes="@MudNoAutofill.noAutoFillAttr"/>
            <MudTextField @bind-Value="@model.Email" InputType="InputType.Email" For="@(() => model.Email)" Label="Email" ReadOnly="false" Variant="Variant.Filled" UserAttributes="@MudNoAutofill.noAutoFillAttr"/>
            <MudTextField @bind-Value="@model.Password" InputType="InputType.Password" For="@(() => model.Password)" Label="Password" ReadOnly="false" Variant="Variant.Filled" UserAttributes="@MudNoAutofill.noAutoFillAttr"/>
            <MudTextField @bind-Value="@model.Password2" InputType="InputType.Password" For="@(() => model.Password2)" Label="Confirm Password" ReadOnly="false" Variant="Variant.Filled" UserAttributes="@MudNoAutofill.noAutoFillAttr"/>
            @if( allRoles != null )
            {
                <MudSelect T=" string " Label="User Roles" HelperText="Select the roles to which this user belongs" @bind-Value="selectedRole" Variant="Variant.Filled">
                    @foreach( var role in allRoles )
                    {
                        <MudSelectItem T=" string " Value="@role.Name">@role.Name</MudSelectItem>
                    }
                </MudSelect>
            }
            @if( !string.IsNullOrEmpty(errorMsg) )
            {
                <p class="adduser-error">Error: @errorMsg</p>
            }
        </EditForm>
    </DialogContent>
    <DialogActions>
        <MudButton OnClick="Cancel">Cancel</MudButton>
        <MudButton Color="Color.Primary" OnClick="Save">@SaveButtonText</MudButton>
    </DialogActions>
</MudDialog>

@code {

    [CascadingParameter] MudDialogInstance MudDialog { get; set; }

    [Parameter] public int? UserID { get; set; }

    AppIdentityUser User;
    bool AddingNewUser { get; set; }
    string SaveButtonText => AddingNewUser ? "Create User" : "Save";

    public class UserForm
    {
        [Required] public string Username { get; set; }

        [Required] [EmailAddress] public string Email { get; set; }

        public string Password { get; set; }
        public string Password2 { get; set; }
    }

    private readonly UserForm model = new();

    private async Task OnValidSubmit(EditContext context)
    {
        await Save();
    }

    private string selectedRole, errorMsg;

    private readonly List<ApplicationRole> allRoles = new();

    private void DisplayError(string errorText)
    {
        errorMsg = errorText;
        StateHasChanged();
    }

    private void DisplayIdentityResultError(UserResponse result)
    {
        if( result != null && result.Errors.Any() )
        {
            var msg = string.Join(", ", result.Errors);
            DisplayError(msg);
        }
    }

    // TODO: Get better return values here and show errors if there are any.
    async Task Save()
    {
        try
        {
            var success = true;

            if( AddingNewUser )
            {
                success = !string.IsNullOrEmpty(model.Password) && model.Password.Equals(model.Password2);

                if( !success )
                {
                    DisplayError("Passwords empty or do not match.");
                }
            }
            else
            {
                // For exsiting users, handle password reset.
                if( !string.IsNullOrEmpty(model.Password) && !model.Password2.StartsWith("*****") )
                {
                    success = model.Password.Equals(model.Password2);

                    if( success )
                    {
                        var result = await userService.SetUserPasswordAsync(model.Username, model.Password);

                        success = result.Succeeded;

                        if( !success )
                            DisplayIdentityResultError(result);
                    }
                    else
                    {
                        DisplayError("Passwords do not match.");
                    }
                }
            }

            if( success )
            {
                User.UserName = model.Username;
                User.Email = model.Email;

                UserResponse result;
                var role = new[] { selectedRole };

                if ( AddingNewUser )
                {
                    result = await userService.CreateNewUser(model.Username, model.Email, model.Password, role);
                }
                else
                {
                    result = await userService.UpdateUserAsync(model.Username, model.Email, role) ;
                }

                success = result != null && result.Succeeded;

                if( success )
                {
                    var msg = AddingNewUser ? "added" : "updated";
                    statusService.UpdateStatus($"User '{User.UserName}' {msg}");
                }
                else
                    DisplayIdentityResultError(result);
            }

            if( success )
            {
                MudDialog.Close(DialogResult.Ok(true));
            }
        }
        catch( Exception ex )
        {
            logger.LogError($"Exception when saving user: {ex}");
            DisplayError("Unexpected error while saving user. Please try again.");
        }
    }

    void Cancel()
    {
        MudDialog.Cancel();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if( firstRender )
        {
            var systemRoles = await userService.GetRoles();

            if( systemRoles != null && systemRoles.Any() )
            {
                var allUsers = await userService.GetUsers();

                if( allUsers.Any() )
                {
                    allRoles.AddRange(systemRoles);

                    if( User.UserRoles != null )
                    {
                        var role = User.UserRoles.First();
                        selectedRole = role.Role.Name;
                    }
                    else
                        selectedRole = RoleDefinitions.s_AdminRole;
                }
                else
                {
                    // Default
                    selectedRole = RoleDefinitions.s_AdminRole;

                    // If there's no users yet, default to Admin
                    var adminRole = systemRoles.FirstOrDefault(x => x.Name == "Admin");
                    allRoles.Add(adminRole);
                }
            }

            StateHasChanged();
        }
    }

    protected override async Task OnInitializedAsync()
    {
        if( UserID is null || UserID == 0 )
        {
            AddingNewUser = true;
            User = new AppIdentityUser();
        }
        else
        {
            User = await userService.GetUser( UserID.Value );
        }

        model.Username = User.UserName;
        model.Email = User.Email;

        await base.OnInitializedAsync();
    }
}